-module(assembler_util).
-author('abdoo.mahran@gmail.com').

%%% Export files
-export([hex2bin/1, dec2bin/1, format/1]).

%%% Include files
-include("assembler.hrl").


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%                                              %%%
%%%               External Functions             %%%
%%%                                              %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Converts Hexadecimal to Binary
%%% @see hex2binl/3
hex2bin(Hex) when is_list(Hex)->
    hex2binl(Hex, length(Hex),[]).

%%% Converts Decimal to Binary
dec2bin(Dec) when is_list(Dec) ->
    dec2binl(list_to_integer(Dec), ?DECIMAL, []).

hex2binl(_Hex, 0, Acc) ->
    string:join(Acc,"");
hex2binl(Hex, N, Acc) ->
    H = string:substr(Hex, N, 1),
    case hex(H) of
        {error, Hex} ->
            {error, Hex};
        Result ->
            hex2binl(Hex, N-1, [Result|Acc])
    end.

%%% Formats output
format(Tab) ->
    io:format("~n=========  Results =============~n"),
    io:format("================================~n"),
    io:format("LC           Code~n"),
    formatl(Tab).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%                                              %%%
%%%               Internal Functions             %%%
%%%                                              %%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
formatl([]) ->
    io:format("================================~n");
formatl([{LC, Code}|T]) ->
    io:format("~p        ~p~n",[list_to_atom(LC), list_to_atom(Code)]),
    formatl(T).

hex("0") ->
    "0000";
hex("1") ->
    "0001";
hex("2") ->
    "0010";
hex("3") ->
    "0011";
hex("4") ->
    "0100";
hex("5") ->
    "0101";
hex("6") ->
    "0110";
hex("7") ->
    "0111";
hex("8") ->
    "1000";
hex("9") ->
    "1001";
hex(A) when A=="A"; A=="a"->
    "1010";
hex(B) when B=="B"; B=="b"->
    "1011";
hex(C) when C=="C"; C=="c"->
    "1100";
hex(D) when D=="D"; D=="d" ->
    "1101";
hex(E) when E=="E"; E=="e" ->
    "1110";
hex(F) when F=="F"; F=="f" ->
    "1111";
hex(Hex) ->
    {error, Hex}.


dec2binl(_Dec, -1, Acc) ->
    string:join(lists:reverse(Acc),"");
dec2binl(Dec, N, Acc) ->
    K = (Dec bsr N),
    case K band 1 of
        1 ->
            dec2binl(Dec, N-1,[integer_to_list(1)| Acc]);
        _ ->
            dec2binl(Dec, N-1,[integer_to_list(0)| Acc])
    end.
